Bellman-Ford 演算法是一種用於解決最短路徑問題的演算法,可以處理包含負權重邊的圖。
演算法
Bellman-Ford 演算法通過不斷嘗試更新節點之間的最短距離,來找到從一個指定的源節點到圖中所有其他節點的最短路徑。
如果存在負權環,則演算法會檢測到它們。這個演算法的時間複雜度為 ,其中 是節點數, 是邊數。
// Bellman Ford Algorithm in Kotlin
class BellmanFord {
fun bellmanFord(graph: Array<IntArray>, V: Int, E: Int, src: Int) {
// Initialize distance of all vertices as infinite.
val dis = IntArray(V)
for (i in 0 until V) dis[i] = Int.MAX_VALUE
// initialize distance of source as 0
dis[src] = 0
// Relax all edges |V| - 1 times. A simple shortest
// path from src to any other vertex can have at-most |V| - 1 edges
for (i in 0 until V - 1) {
for (j in 0 until E) {
if (dis[graph[j][0]] != Int.MAX_VALUE && dis[graph[j][0]] + graph[j][2] < dis[graph[j][1]])
dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]
}
}
// check for negative-weight cycles.
for (i in 0 until E) {
val x = graph[i][0]
val y = graph[i][1]
val weight = graph[i][2]
if (dis[x] != Int.MAX_VALUE && dis[x] + weight < dis[y])
println("Graph contains negative weight cycle")
}
println("Vertex Distance from Source")
for (i in 0 until V) println("$i\t\t${dis[i]}")
}
}
// main function
fun main(args: Array<String>) {
val V = 5 // Number of vertices in graph
val E = 8 // Number of edges in graph
// Every edge has three values (u, v, w) where
// the edge is from vertex u to v. And weight
// of the edge is w.
val graph = arrayOf(
intArrayOf(0, 1, -1),
intArrayOf(0, 2, 4),
intArrayOf(1, 2, 3),
intArrayOf(1, 3, 2),
intArrayOf(1, 4, 2),
intArrayOf(3, 2, 5),
intArrayOf(3, 1, 1),
intArrayOf(4, 3, -3)
)
val bellmanFord = BellmanFord()
bellmanFord.bellmanFord(graph, V, E, 0)
}
Floyd-Warshall 演算法是一種用於解決所有節點對之間最短路徑問題的演算法。
它適用於有向圖或帶權有向圖,其中每條邊都有一個非負權重。
演算法
Floyd-Warshall 演算法的時間複雜度是,其中是節點的數量。
優點是它可以處理包含負權邊的圖,並且它能夠找到所有節點對之間的最短路徑,而不僅僅是一對節點之間的最短路徑。
然而,對於大型圖,它的運行時間可能會變得很長。
// Floyd-Warshall Algorithm in Kotlin
// INF
val INF = 99999
class FloydWarshall {
// Number of vertices in the graph
private val V = 4
// Define infinity as the large enough value. This value will be
// used for vertices not connected to each other
private val INF = 99999
// Solves the all-pairs shortest path problem using Floyd Warshall algorithm
fun floydWarshall(graph: Array<IntArray>) {
/* dist[][] will be the output matrix that will finally
have the shortest distances between every pair of vertices */
val dist = Array(V) { IntArray(V) }
var i: Int
var j: Int
var k: Int
/* Initialize the solution matrix same as input graph matrix.
Or we can say the initial values of shortest distances
are based on shortest paths considering no intermediate
vertex. */
i = 0
while (i < V) {
j = 0
while (j < V) {
dist[i][j] = graph[i][j]
j++
}
i++
}
/* Add all vertices one by one to the set of intermediate
vertices.
---> Before start of an iteration, we have shortest
distances between all pairs of vertices such that
the shortest distances consider only the vertices in
set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of an iteration, vertex no. k is
added to the set of intermediate vertices and the
set becomes {0, 1, 2, .. k} */
k = 0
while (k < V) {
// Pick all vertices as source one by one
i = 0
while (i < V) {
// Pick all vertices as destination for the
// above picked source
j = 0
while (j < V) {
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j]
j++
}
i++
}
k++
}
// Print the shortest distance matrix
printSolution(dist)
}
/* A utility function to print solution */
fun printSolution(dist: Array<IntArray>) {
println("The following matrix shows the shortest " + "distances between every pair of vertices")
var i = 0
while (i < V) {
var j = 0
while (j < V) {
if (dist[i][j] == INF)
print("%7s".format("INF"))
else
print("%7d".format(dist[i][j]))
j++
}
println()
i++
}
}
}
// main function
fun main(args: Array<String>) {
/* Let us create the following weighted graph
10
(0)------->(3)
| /|\
5 | |
| | 1
\|/ |
(1)------->(2)
3 */
val graph = arrayOf(intArrayOf(0, 5, INF, 10),
intArrayOf(INF, 0, 3, INF),
intArrayOf(INF, INF, 0, 1),
intArrayOf(INF, INF, INF, 0))
val a = FloydWarshall()
// Print the solution
a.floydWarshall(graph)
}
所有 Code 可以在 Github 找到 ~
明天會接著介紹 Prim's Algorithm 和 Kruskal's Algorithm